using System;
using Habanero.Base.Exceptions;
using UseCaseManager.BO;
using NUnit.Framework;

namespace UseCaseManager.Test.BO
{
    /// <summary>
    /// Provides a place to write custom tests for Release objects.
    /// This file is only written once and can be changed.  The Def file
    /// attached to this as a dependent is rewritten with each regeneration
    /// and contains the standard tests for Release.
    /// Regenerate this test project whenever there have been changes to the
    /// business objects.
    /// If tests are failing due to a unique setup in your application,
    /// you can either override the Create methods in TestUtils, or you
    /// can add the test to the ignore list below and reimplement it here.
    /// </summary>
    public partial class TestRelease
    {
        [TestFixtureSetUp]
        public void SetupTestFixture()
        {
            //------------------------------------------------------------
            // Use this list to ignore generated tests that are failing
            // due to a unique condition in your application.
            // Remember to reimplement the test here.
            //------------------------------------------------------------
            //_ignoreList.Add("TestMethodName", "Reason for ignoring it");
            base.TestFixtureSetup();
        }

        [Test]
        public void Test_ToString()
        {
            //---------------Set up test pack-------------------
            Release release = TestUtilsRelease.CreateUnsavedValidRelease();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            string actualString = release.ToString();
            //---------------Test Result -----------------------
            Assert.AreEqual(release.ReleaseName, actualString);
        }
        
        [Test]
        public void Test_Calculate_PointsAssigned_TwoDrops_Release()
        {
            //---------------Set up test pack-------------------
            Drop drop;
            Drop drop2;
            Release release = TestUtilsRelease.CreateRelease2Drops_FirstDrop_3UseCases_SecondDrop_2UseCases
                (out drop, out drop2);
            const int expectedNumberOfUseCasesDrop1 = 3;
            const int expectedNumberOfUseCasesDrop2 = 2;
            const int expectedNumberOfDrops = 2;
            //---------------Assert Precondition----------------
            Assert.AreEqual(expectedNumberOfUseCasesDrop1, drop.UseCases.Count);
            Assert.AreEqual(expectedNumberOfUseCasesDrop2, drop2.UseCases.Count);
            Assert.AreEqual(expectedNumberOfDrops, release.Drops.Count);
            //---------------Execute Test ----------------------
            int totalPoints = release.PointsAssigned;
            //---------------Test Result -----------------------
            int expectedTotalPoints = (drop.PointsAssigned.GetValueOrDefault() + drop2.PointsAssigned.GetValueOrDefault());
            Assert.AreEqual(expectedTotalPoints, totalPoints);
        }

        [Test]
        public void Test_Calculate_PointsBaseline_TwoDrops_Release()
        {
            //---------------Set up test pack-------------------
            Drop drop;
            Drop drop2;
            Release release = TestUtilsRelease.CreateRelease2Drops_FirstDrop_3UseCases_SecondDrop_2UseCases
                (out drop, out drop2);
            const int expectedNumberOfUseCasesDrop1 = 3;
            const int expectedNumberOfUseCasesDrop2 = 2;
            const int expectedNumberOfDrops = 2;
            //---------------Assert Precondition----------------
            Assert.AreEqual(expectedNumberOfUseCasesDrop1, drop.UseCases.Count);
            Assert.AreEqual(expectedNumberOfUseCasesDrop2, drop2.UseCases.Count);
            Assert.AreEqual(expectedNumberOfDrops, release.Drops.Count);
            //---------------Execute Test ----------------------
            int totalBaselinePoints = release.PointsBaseline;
            //---------------Test Result -----------------------
            int expectedTotalBaselinePoints = drop.PointsBaseline.GetValueOrDefault() + drop2.PointsBaseline.GetValueOrDefault();
            Assert.AreEqual(expectedTotalBaselinePoints, totalBaselinePoints);
        }

        [Test]
        public void Test_Calculate_PointsCompleted_TwoDrops_Release()
        {
            //---------------Set up test pack-------------------
            Drop drop;
            Drop drop2;
            Release release = TestUtilsRelease.CreateRelease2Drops_FirstDrop_3UseCases_SecondDrop_2UseCases
                (out drop, out drop2);
            const int expectedNumberOfUseCasesDrop1 = 3;
            const int expectedNumberOfUseCasesDrop2 = 2;
            const int expectedNumberOfDrops = 2;
            drop.UseCases[0].CompletedInDropID = drop.DropID;
            drop.UseCases[1].CompletedInDropID = null;
            drop.UseCases[2].CompletedInDropID = drop2.DropID;
            drop2.UseCases[0].CompletedInDropID = null;
            drop2.UseCases[1].CompletedInDropID = drop2.DropID;
            //---------------Assert Precondition----------------
            Assert.AreEqual(expectedNumberOfUseCasesDrop1, drop.UseCases.Count);
            Assert.AreEqual(expectedNumberOfUseCasesDrop2, drop2.UseCases.Count);
            Assert.AreEqual(expectedNumberOfDrops, release.Drops.Count);
            //---------------Execute Test ----------------------
            int totalPointsCompleted = release.PointsCompleted;
            //---------------Test Result -----------------------
            int expectedTotalPointsCompleted = drop.PointsCompleted.GetValueOrDefault() + drop2.PointsCompleted.GetValueOrDefault();
            Assert.AreEqual(expectedTotalPointsCompleted, totalPointsCompleted);
        }

        [Test]
        public void Test_Calculate_AssignedPointsRemaining_TwoDrops()
        {
            //---------------Set up test pack-------------------
            Drop drop;
            Drop drop2;
            Release release = TestUtilsRelease.CreateUnsavedRelease2DropsOrderdByEndDate(out drop, out drop2);
            //---------------Assert Precondition----------------
            Assert.AreNotEqual(0, drop.PointsAssigned);
            Assert.AreNotEqual(0, drop2.PointsAssigned);
            Assert.AreEqual(0, drop.CumulativePointsAssignedRemaining);
            Assert.AreEqual(0, drop.CumulativePointsAssignedRemaining);
            Assert.AreEqual(2, release.Drops.Count);
            //---------------Execute Test ----------------------
            release.AssignCumulativePointsAssignedRemainingToDrops();
            //---------------Test Result -----------------------
            Assert.AreEqual(release.PointsAssigned - drop.PointsAssigned, drop.CumulativePointsAssignedRemaining);
            Assert.AreEqual(0, drop2.CumulativePointsAssignedRemaining, "this is the last drop and there should therefore be no points remaining");
        }

        [Test]
        public void Test_Calculate_AssignedPointsRemaining_ThreeDrops()
        {
            //---------------Set up test pack-------------------
            Drop drop;
            Drop drop1;
            Drop drop2;
            Release release = TestUtilsRelease.CreateUnsavedRelease3DropsOrderdByEndDate(out drop, out drop1, out drop2);
            //---------------Assert Precondition----------------
            Assert.AreNotEqual(0, drop.PointsAssigned);
            Assert.AreNotEqual(0, drop1.PointsAssigned);
            Assert.AreNotEqual(0, drop2.PointsAssigned);
            Assert.AreEqual(0, drop.CumulativePointsAssignedRemaining);
            Assert.AreEqual(0, drop1.CumulativePointsAssignedRemaining);
            Assert.AreEqual(0, drop2.CumulativePointsAssignedRemaining);
            Assert.AreEqual(3, release.Drops.Count);
            //---------------Execute Test ----------------------
            release.AssignCumulativePointsAssignedRemainingToDrops();
            //---------------Test Result -----------------------
            Assert.AreEqual(release.PointsAssigned - drop.PointsAssigned, drop.CumulativePointsAssignedRemaining);
            Assert.AreEqual(drop.CumulativePointsAssignedRemaining - drop1.PointsAssigned, drop1.CumulativePointsAssignedRemaining);
            Assert.AreEqual(0, drop2.CumulativePointsAssignedRemaining, "this is the last drop and there should therefore be no points remaining");
        }

        [Test]
        public void Test_Calculate_BaselinePointsRemaining_OneDrop()
        {
            //---------------Set up test pack-------------------
            Release release = TestUtilsRelease.CreateUnsavedValidRelease();
            int expectedTotalAssignedPoints;
            const int expectedNumberOfUseCases = 5;
            const int expectedNumberOfDrops = 1;
            Drop drop = TestUtilsDrop.CreateSavedDrop_WUseCases
                (expectedNumberOfUseCases, out expectedTotalAssignedPoints);
            release.Drops.Add(drop);
            int expectedBaselinePointsRemaining = release.PointsBaseline - drop.PointsBaseline.GetValueOrDefault();
            //---------------Assert Precondition----------------
            Assert.AreEqual(expectedNumberOfUseCases, drop.UseCases.Count);
            Assert.AreEqual(expectedNumberOfDrops, release.Drops.Count);
            Assert.AreEqual(0, expectedBaselinePointsRemaining);
            //---------------Execute Test ----------------------
            release.AssignCumulativePointsBaselineRemainingToDrops();
            //---------------Test Result -----------------------
            Assert.AreEqual(expectedBaselinePointsRemaining, drop.CumulativePointsBaselineRemaining);
        }

        [Test]
        public void Test_Calculate_BaselinePointsRemaining_TwoDrops()
        {
            //---------------Set up test pack-------------------
            Drop drop;
            Drop drop2;
            Release release = TestUtilsRelease.CreateUnsavedRelease2DropsOrderdByEndDate(out drop, out drop2);
            //---------------Assert Precondition----------------
            Assert.AreNotEqual(0, drop.PointsAssigned);
            Assert.AreNotEqual(0, drop2.PointsAssigned);
            Assert.AreEqual(0, drop.CumulativePointsBaselineRemaining);
            Assert.AreEqual(0, drop.CumulativePointsBaselineRemaining);
            Assert.AreEqual(2, release.Drops.Count);
            //---------------Execute Test ----------------------
            release.AssignCumulativePointsBaselineRemainingToDrops();
            //---------------Test Result -----------------------
            Assert.AreEqual(release.PointsBaseline - drop.PointsBaseline, drop.CumulativePointsBaselineRemaining);
            Assert.AreEqual(0, drop2.CumulativePointsBaselineRemaining, "this is the last drop and there should therefore be no points remaining");
        }

        [Test]
        public void Test_Calculate_TotalDropPointsBaseline_Release_BaselinePointsNull()
        {
            //---------------Set up test pack-------------------
            Release release = TestUtilsRelease.CreateSavedRelease();
            int expectedTotalPoints;
            int expectedBaselineTotalPoints;
            const int expectedNumberOfUseCases = 3;
            const int expectedNumberOfDrops = 1;
            Drop drop = TestUtilsDrop.CreateSavedDrop_WUseCases_BaseLinePointsNull_AssignedPointsNull(expectedNumberOfUseCases, out expectedTotalPoints, out expectedBaselineTotalPoints);
            release.Drops.Add(drop);
            release.Save();
            //---------------Assert Precondition----------------
            Assert.AreEqual(expectedNumberOfUseCases, drop.UseCases.Count);
            Assert.AreEqual(expectedNumberOfDrops, release.Drops.Count);
            Assert.AreEqual(0, expectedTotalPoints);
            //---------------Execute Test ----------------------
            int totalPoints = drop.PointsBaseline.Value;
            //---------------Test Result -----------------------
            Assert.AreEqual(expectedTotalPoints, totalPoints);
        }

        [Test]
        public void Test_Calculate_TotalDropPointsAssigned_Release_AssignedPointsNull()
        {
            //---------------Set up test pack-------------------
            Release release = TestUtilsRelease.CreateSavedRelease();
            int expectedTotalPoints;
            int expectedBaselineTotalPoints;
            const int expectedNumberOfUseCases = 3;
            const int expectedNumberOfDrops = 1;
            Drop drop = TestUtilsDrop.CreateSavedDrop_WUseCases_AssignedPointNull(expectedNumberOfUseCases, out expectedTotalPoints, out expectedBaselineTotalPoints);
            release.Drops.Add(drop);
            release.Save();
            //---------------Assert Precondition----------------
            Assert.AreEqual(expectedNumberOfUseCases, drop.UseCases.Count);
            Assert.AreEqual(expectedNumberOfDrops, release.Drops.Count);
            Assert.AreEqual(0, expectedTotalPoints);
            //---------------Execute Test ----------------------
            int totalPoints = drop.PointsAssigned.Value;
            //---------------Test Result -----------------------
            Assert.AreEqual(expectedTotalPoints, totalPoints);
        }

        [Test]
        public void Test_Calculate_TotalDropPointsAssigned_Release()
        {
            //---------------Set up test pack-------------------
            Release release = TestUtilsRelease.CreateSavedRelease();
            int expectedTotalPoints;
            const int expectedNumberOfUseCases = 3;
            const int expectedNumberOfDrops = 1;
            Drop drop = TestUtilsDrop.CreateSavedDrop_WUseCases(expectedNumberOfUseCases, out expectedTotalPoints);
            release.Drops.Add(drop);
            release.Save();
            //---------------Assert Precondition----------------
            Assert.AreEqual(expectedNumberOfUseCases, drop.UseCases.Count);
            Assert.AreEqual(expectedNumberOfDrops, release.Drops.Count);
            //---------------Execute Test ----------------------
            int totalPoints = drop.PointsAssigned.GetValueOrDefault();
            //---------------Test Result -----------------------
            Assert.AreEqual(expectedTotalPoints, totalPoints);
        }

        [Test]
        public void Test_Calculate_BaselinePointsRemaining_ThreeDrops()
        {
            //---------------Set up test pack-------------------
            Drop drop;
            Drop drop1;
            Drop drop2;
            Release release = TestUtilsRelease.CreateUnsavedRelease3DropsOrderdByEndDate(out drop, out drop1, out drop2);
            //---------------Assert Precondition----------------
            Assert.AreNotEqual(0, drop.PointsBaseline);
            Assert.AreNotEqual(0, drop1.PointsBaseline);
            Assert.AreNotEqual(0, drop2.PointsBaseline);
            Assert.AreEqual(0, drop.CumulativePointsBaselineRemaining);
            Assert.AreEqual(0, drop1.CumulativePointsBaselineRemaining);
            Assert.AreEqual(0, drop2.CumulativePointsBaselineRemaining);
            Assert.AreEqual(3, release.Drops.Count);
            //---------------Execute Test ----------------------
            release.AssignCumulativePointsBaselineRemainingToDrops();
            //---------------Test Result -----------------------
            Assert.AreEqual(release.PointsBaseline - drop.PointsBaseline, drop.CumulativePointsBaselineRemaining);
            Assert.AreEqual(drop.CumulativePointsBaselineRemaining - drop1.PointsBaseline, drop1.CumulativePointsBaselineRemaining);
            Assert.AreEqual(0, drop2.CumulativePointsBaselineRemaining, "this is the last drop and there should therefore be no points remaining");
        }

        [Test]
        public void Test_CannotCreateDrops_DropsExist()
        {
            //---------------Set up test pack-------------------
            Release release = TestUtilsRelease.CreateUnsavedValidRelease();
            release.Drops.CreateBusinessObject();
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, release.Drops.Count);
            //---------------Execute Test ----------------------
            try
            {
                release.CreateDrops();
                Assert.Fail("expected Err");
            }
            //---------------Test Result -----------------------
            catch (UserException ex)
            {
                StringAssert.Contains("You cannot create drops since the release already has drops", ex.Message);
            }
        }

        [Test]
        public void Test_CreateDrops_1Drop()
        {
            //---------------Set up test pack-------------------
            Release release = TestUtilsRelease.CreateUnsavedValidRelease();
            release.StartWorkDate = new DateTime(2008, 3, 2);
            release.EndWorkDate = new DateTime(2008, 3, 8);
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            release.CreateDrops();
            //---------------Test Result -----------------------
            Assert.AreEqual(1, release.Drops.Count);
            Drop drop = release.Drops[0];
            Assert.AreEqual(release.StartWorkDate, drop.StartDate);
            Assert.AreEqual(release.EndWorkDate, drop.EndDate);
            Assert.AreEqual("Week 1", drop.Name);
            Assert.IsFalse(drop.Status.IsNew);
        }
        [Test]
        public void Test_CreateDrops_2Drops()
        {
            //---------------Set up test pack-------------------
            Release release = TestUtilsRelease.CreateUnsavedValidRelease();
            release.StartWorkDate = new DateTime(2008, 3, 2);
            release.EndWorkDate = new DateTime(2008, 3, 15);
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            release.CreateDrops();
            //---------------Test Result -----------------------
            Assert.AreEqual(2, release.Drops.Count);
            Drop drop = release.Drops[0];
            Assert.AreEqual(release.StartWorkDate, drop.StartDate);
            Assert.AreEqual(release.StartWorkDate.Value.AddDays(6), drop.EndDate);
            Assert.AreEqual("Week 1", drop.Name);
            Drop drop2 = release.Drops[1];
            Assert.AreEqual(release.StartWorkDate.Value.AddDays(7), drop2.StartDate);
            Assert.AreEqual(release.StartWorkDate.Value.AddDays(13), drop2.EndDate);
            Assert.AreEqual("Week 2", drop2.Name);
        }
        [Test]
        public void Test_CreateDrops_3Drops()
        {
            //---------------Set up test pack-------------------
            Release release = TestUtilsRelease.CreateUnsavedValidRelease();
            release.StartWorkDate = new DateTime(2008, 3, 2);
            release.EndWorkDate = new DateTime(2008, 3, 22);
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            release.CreateDrops();
            //---------------Test Result -----------------------
            Assert.AreEqual(3, release.Drops.Count);
            Drop drop = release.Drops[0];
            Assert.AreEqual(release.StartWorkDate, drop.StartDate);
            Assert.AreEqual(release.StartWorkDate.Value.AddDays(6), drop.EndDate);
            Drop drop2 = release.Drops[1];
            Assert.AreEqual(release.StartWorkDate.Value.AddDays(7), drop2.StartDate);
            Assert.AreEqual(release.StartWorkDate.Value.AddDays(13), drop2.EndDate);
            Drop drop3 = release.Drops[2];
            Assert.AreEqual(release.StartWorkDate.Value.AddDays(14), drop3.StartDate);
            Assert.AreEqual(release.StartWorkDate.Value.AddDays(20), drop3.EndDate);
            Assert.AreEqual("Week 3", drop3.Name);
        }

        [Test]
        public void Test_StartDateNotNull()
        {
            //---------------Set up test pack-------------------
            Release release = TestUtilsRelease.CreateUnsavedValidRelease();
            release.StartWorkDate = null;
            release.EndWorkDate = new DateTime(2008, 3, 2);
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            try
            {
                release.CreateDrops();
                Assert.Fail("expected Err");
            }
            //---------------Test Result -----------------------
            catch (UserException ex)
            {
                StringAssert.Contains("The release must have a StartWorkDate", ex.Message);
            }
        }

        [Test]
        public void Test_EndWorkDateNotNull()
        {
            //---------------Set up test pack-------------------
            Release release = TestUtilsRelease.CreateUnsavedValidRelease();
            release.StartWorkDate = new DateTime(2008, 3, 2);
            release.EndWorkDate = null;
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            try
            {
                release.CreateDrops();
                Assert.Fail("expected Err");
            }
            //---------------Test Result -----------------------
            catch (UserException ex)
            {
                StringAssert.Contains("The release must have a EndWorkDate", ex.Message);
            }
        }

        [Test]
        public void Test_DatesAreValid()
        {
            //---------------Set up test pack-------------------
            Release release = TestUtilsRelease.CreateUnsavedValidRelease();
            release.StartWorkDate = new DateTime(2008, 3, 22);
            release.EndWorkDate = new DateTime(2008, 3, 2);
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            try
            {
                release.CreateDrops();
                Assert.Fail("expected Err");
            }
            //---------------Test Result -----------------------
            catch (UserException ex)
            {
                StringAssert.Contains("The StartWorkDate is after the EndWorkDate", ex.Message);
            }
        }


    }
}